همان طور که در قسمت سي و يکم توضيح داده شد، دو حالت از Operator Method وجود دارد: Unary Operators و Binary Operators که با Binary Operators نيز آشنا شديد. Unary Operator ها مانند Binary Operator ها overload مي شوند و با اين تفاوت سایت که در Unary Operators تنها يک operand وجود دارد.
فرم کلي Unary Operators به شکل زير است:
// General form for overloading a unary operator
public static ret-type operator op(param-type operand)
{
// operations
}
در اين جا يک شيء جديد retuمي شود که شامل مقدار منفي فيلدهاي operand است. دقت کنيد که operand تغيير نمي کند، براي مثال در عبارت a = -b مقدار منفي b به a اختصاص داده مي شود در حالي که b بدون تغيير مي ماند.
using System;
class TwoD
{
private int X, Y;
public TwoD()
{
X = Y = 1;
}
public TwoD(int a, int b)
{
X = a;
Y = b;
}
public static TwoD operator -(TwoD ob)
{
TwoD result = new TwoD();
result.X = -ob.X;
result.Y = -ob.Y;
retu result;
}
public void Show()
{
Console.WriteLine("{0}, {1}", X, Y);
}
}
class UnaryOpertorDemo
{
static void Main()
{
TwoD ob = new TwoD(1, 1);
TwoD result;
result = -ob;
ob.Show();
result.Show();
}
}
در سي شارپ، overload کردن ++ و - - بسيار آسان است. کافي است که مقدار را افزايش يا کاهش دهيد و آن را retu کنيد اما نبايد مقدار شيء operand را تغيير دهيد. سي شارپ به طور خودکار حالت هاي postfix و prefix را براي شما در نظر مي گيرد. براي مثال متد زير يک ()++operator براي کلاس TwoD است:
using System;
class TwoD
{
int X, Y;
public TwoD()
{
X = Y = 0;
}
public TwoD(int a, int b)
{
X = a;
Y = b;
}
// Overload binary +
public static TwoD operator +(TwoD ob1, TwoD ob2)
{
TwoD result = new TwoD();
result.X = ob1.X + ob2.X;
result.Y = ob1.Y + ob2.Y;
retu result;
}
// Overload binary -
public static TwoD operator -(TwoD ob1, TwoD ob2)
{
TwoD result = new TwoD();
result.X = ob1.X - ob2.X;
result.Y = ob1.Y - ob2.Y;
retu result;
}
// Overload unary -
public static TwoD operator -(TwoD ob)
{
TwoD result = new TwoD();
result.X = -ob.X;
result.Y = -ob.Y;
retu result;
}
// Overload unary ++
public static TwoD operator ++(TwoD ob)
{
TwoD result = new TwoD();
result.X = ob.X + 1;
result.Y = ob.Y + 1;
retu result;
}
// Overload unary --
public static TwoD operator --(TwoD ob)
{
TwoD result = new TwoD();
result.X = ob.X - 1;
result.Y = ob.Y - 1;
retu result;
}
public void Show()
{
Console.WriteLine(X + ", " + Y);
}
}
class OpOverloadingDemo
{
static void Main()
{
TwoD a = new TwoD();
TwoD b = new TwoD(1, 2);
TwoD c = new TwoD(5, 5);
Console.Write("Here is a : ");
a.Show();
Console.Write("Here is b : ");
b.Show();
Console.Write("Here is c : ");
c.Show();
Console.WriteLine();
a++;
Console.Write("Here is a after a++ : ");
a.Show();
a--;
Console.Write("Here is a after a-- : ");
a.Show();
Console.WriteLine();
a = c;
Console.Write("Here is a after a = c : ");
a.Show();
a = c + b;
Console.Write("Here is a after a = c + b : ");
a.Show();
a = b - c;
Console.Write("Here is a after a = b - c : ");
a.Show();
Console.WriteLine();
a = -b;
Console.Write("Here is a after a = -b : ");
a.Show();
Console.Write("Here is b after a = -b : ");
b.Show();
Console.WriteLine();
// reset objects
a = new TwoD(1, 1);
b = new TwoD(2, 2);
c = new TwoD();
Console.Write("Here is a : ");
a.Show();
Console.Write("Here is b : ");
b.Show();
Console.Write("Here is c : ");
c.Show();
Console.WriteLine();
c = a++;
Console.Write("Here is c after c = a++ : ");
c.Show();
Console.Write("Here is a after c = a++ : ");
a.Show();
Console.WriteLine();
c = ++a;
Console.Write("Here is c after c = ++a : ");
c.Show();
Console.Write("Here is a after c = ++a : ");
a.Show();
c = --a;
Console.Write("Here is c after c = --a : ");
c.Show();
c = a--;
Console.Write("Here is c after c = a-- : ");
c.Show();
}
}
خروجي:
شما مي توانيد operator methods را هم overload کنيد. رايج ترين دليل آن اين است که با اين کار اين امکان را فراهم مي کنيد تا عمليات بين يک class type (مثل کلاسي که خودتان تعريف کرديد) و يک built-in type (يک type که در دات نت موجود است، مثل int) انجام شود. به عنوان مثال، مجدداً به کلاس TwoD دقت کنيد. مشاهده کرديد که + را overload کرده ايم و اين باعث مي شود تا مختصات يک شيء TwoD با مختصات يک شيء ديگر جمع شود. اما اين تنها راه جمع کردن براي شيء TwoD نيست! شما فقط توانستيد دو شيء را با هم جمع کنيد اما گاهي نياز داريد يک int را با يک شيء جمع کنيد. براي اين منظور شما نياز داريد که + را دوباره overload کنيد
// Overload binary + for TwoD + int.
public static TwoD operator +(TwoD op1, int op2)
{
TwoD result = new TwoD();
result.X = op1.X + op2;
result.Y = op1.Y + op2;
retu result;
}
دقت کنيد که پارامتر دوم از جنس int است. بنابراين اين متد اجازه مي دهد يک مقدار int به هر يک از فيلدهاي TwoD افزوده شود. توجه داشته باشيد هنگامي که يک binary operator را overload مي کنيد، يکي از operand ها حتماً بايد از جنس کلاسي باشد که در آن operand مربوطه overload مي شود اما بقيه ي operand ها مي توانند از هر نوعي باشند. به همين دليل است که در متد قبل يکي از parameter ها از جنس TwoD (جنس کلاسي که در آن operand مورد نظر overload شده) و ديگري از يک جنس دل خواه مثل int است.
در زير مشاهده مي کنيد که + دو بار overload شده دارد:
using System;
class TwoD
{
int X, Y;
public TwoD()
{
X = Y = 0;
}
public TwoD(int a, int b)
{
X = a;
Y = b;
}
// Overload binary + for TwoD + int.
public static TwoD operator +(TwoD op1, int op2)
{
TwoD result = new TwoD();
result.X = op1.X + op2;
result.Y = op1.Y + op2;
retu result;
}
// Overload binary + for TwoD + TwoD.
public static TwoD operator +(TwoD op1, TwoD op2)
{
TwoD result = new TwoD();
result.X = op1.X + op2.X;
result.Y = op1.Y + op2.Y;
retu result;
}
public void Show()
{
Console.WriteLine(X + ", " + Y);
}
}
class OpOverloadingDemo
{
static void Main()
{
TwoD ob1 = new TwoD();
TwoD ob2 = new TwoD(3, 3);
TwoD result;
result = ob1 + 2; // TwoD + int
ob1.Show();
result.Show();
result += ob2; // TwoD + TwoD
ob2.Show();
result.Show();
}
}
همان طور که مي بينيد، هنگامي که + روي دو شيء TwoD اعمال شده، مختصات اين دو شيء با هم جمع مي شود و هنگامي که + روي يک شيء TwoD و يک مقدار int اعمال شده ، فيلدهاي شيء با مقدار int جمع شده است.
overload کردن + کاربرد مفيدي را به کلاس TwoD مي افزايد اما هنوز اين تمام چيزي نيست که مورد نياز است و در واقع کار هنوز تمام نشده است. متد (operator+(TwoD, int تنها براي عبارتي از اين جمله:
ob1 = ob2 + 10;
مجاز است و عبارتي مثل:
ob1 = 10 + ob2;
را نمي پذيرد. به اين دليل که argument عدد صحيح، دومين argument است يعني آن operand که در سمت راست قرار دارد. اما در عبارت قبلي مي بينيد که argument عدد صحيح را در سمت چپ قرار داده ايم. براي اين که هر دو عبارت براي استفاده مجاز باشند، بايد يک بار ديگر + را overload کنيد. اين بار بايد اولين پارامتر را int و دومين پارامتر را TwoD در نظر بگيريد.
به اين ترتيب، يک ورژن از متد ()+operator براي TwoD + int و يک ورژن ديگر آن براي int + TwoD است. Overload کردن + (يا هر binary operator ديگري) به اين شکل باعث مي شود تا يک built-in type هم بتواند در سمت چپ و هم در سمت راست قرار بگيرد. در نمونه ي زير مي بينيد که چگونه + همان گونه که شرح داده شد، overload شده است:
using System;
class TwoD
{
int X, Y;
public TwoD()
{
X = Y = 0;
}
public TwoD(int a, int b)
{
X = a;
Y = b;
}
// Overload binary + for TwoD + int.
public static TwoD operator +(TwoD op1, int op2)
{
TwoD result = new TwoD();
result.X = op1.X + op2;
result.Y = op1.Y + op2;
retu result;
}
// Overload binary + for int + TwoD.
public static TwoD operator +(int op1, TwoD op2)
{
TwoD result = new TwoD();
result.X = op1 + op2.X;
result.Y = op1 + op2.Y;
retu result;
}
// Overload binary + for TwoD + TwoD.
public static TwoD operator +(TwoD op1, TwoD op2)
{
TwoD result = new TwoD();
result.X = op1.X + op2.X;
result.Y = op1.Y + op2.Y;
retu result;
}
public void Show()
{
Console.WriteLine(X + ", " + Y);
}
}
class OpOverloadingDemo
{
static void Main()
{
TwoD a = new TwoD(1, 2);
TwoD b = new TwoD(10, 10);
TwoD c = new TwoD();
Console.Write("Here is a: ");
a.Show();
Console.WriteLine();
Console.Write("Here is b: ");
b.Show();
Console.WriteLine();
c = a + b; // TwoD + TwoD
Console.Write("Result of a + b: ");
c.Show();
Console.WriteLine();
c = b + 10; // TwoD + int
Console.Write("Result of b + 10: ");
c.Show();
Console.WriteLine();
c = 15 + b; // int + TwoD
Console.Write("Result of 15 + b: ");
c.Show();
}
}
overload کردن عملگرهاي رابطه اي
عملگرهاي رابطه اي (Relational Operators)، مثل == يا > مي توانند به سادگي overload شوند. به طور معمول، يک عملگر رابطه اي overload شده، مقدار true يا false را retu مي کند، به اين دليل که حالت و کاربرد استاندارد عملگرهاي رابطه اي حفظ شود و بتوان از آن ها در عبارت هاي شرطي استفاده کرد. اگر در اين موارد به جاي مقادير bool چيزي ديگري را retu کنيد، به شدت کاربرد اين operator را محدود کرده ايد. نکته ي مهم ديگر اين جاست که بايستي relational operators را به طور جفتي overload کنيد. به عنوان مثال اگر > را overload کرديد، بايستي < را نيز overload کنيد. اين مورد براي operator هاي (<= و >=) و (== و !=) نيز صادق است.
using System;
class TwoD
{
int X, Y;
public TwoD()
{
X = Y = 0;
}
public TwoD(int a, int b)
{
X = a;
Y = b;
}
public static bool operator <(TwoD op1, TwoD op2)
{
retu ((op1.X < op2.X) && (op1.X < op2.Y));
}
public static bool operator >(TwoD op1, TwoD op2)
{
retu ((op1.X > op2.X) && (op1.Y > op2.Y));
}
در مثال بالا، (operator>(TwoD, TwoD در صورتي true را retu مي کند که هم X و هم Y شيء اول از X و Y شيء دوم بزرگ تر باشد. (operator<(TwoD, TwoD در صورتي مقدار true را retu مي کند که هم X و هم Y شيء اول از X و Y شيء دوم کوچک تر باشد.
نکته ي ديگر اين که اگر مي خواهيد operator هاي == و =! را overload کنيد، بايستي متدهاي ()Object.Equels و ()Object.GetHashCode را نيز override کنيد. در مورد اين متدها و تکنيک overriding بعداً صحبت خواهيم کرد.
برچسب: طراحی وب سایت, طراحی سایت, طراحی وب,
نویسنده: sara
تاريخ: چهارشنبه
16 مرداد
1392 ساعت: 15:43